import turbogears   as tg

import logging
import cherrypy
import sqlobject
import re
from string import split
import kaizen
from sqlalchemy.exceptions import SQLError
from sqlalchemy            import and_, or_
from kaizen.model import Action, Tag, Project, Context, session
from turbogears import identity, expose, validate, validators, redirect, error_handler, flash, view
from formencode import validators


log = logging.getLogger("kaizen.subcontrollers.action")

class ActionController:

    @expose(content_type='text/html; charset=utf-8')
    @validate(validators={"title" : validators.NotEmpty()})
    @validate(validators={"previousPage" : validators.NotEmpty()})
    @validate(validators={"contextId" : validators.NotEmpty()})
    @error_handler()
    def save(self, title, notes, projectId, contextId, priority, id, previousPage, tg_errors=None, **keywords):
        if tg_errors:
            log.debug("no title")
            tg.flash("You must enter a title")
            return dict()
        project = None
        if projectId:
           project= session.get(Project,(int(projectId)))

        context= session.get(Context,(int(contextId)))
        if id:

            #update
            try:
              log.debug("update Action. Title = " +title +".")
              print "id = " +str(id)
              action = session.get(Action,(int(id)))
              log.debug("updating")
              action.title=title
              action.notes=notes
              action.project=project
              action.context=context
              action.priority=int(priority)
              action.closed=False
              action.flush()
              log.debug("update done")
            #todo add code completion

            except SQLError,x:
               log.error("error: ", x)
               tg.flash("Action already exists")
               return dict(project=project)
            tg.flash("Action updated")
        else:
            #save
            try:
              action = Action(title=title, notes=notes, project=project, context=context, priority=int(priority), closed=0)
              log.debug('saving action')
              action.flush()
              #todo add code completion
            except SQLError,x:
               log.error("error: ", x)
               tg.flash("internal error")
               return dict(project=project)
            tg.flash("Action added")
        log.debug("returning page")
        return dict(project=project, context=context, tg_template=str(previousPage), previousPage=previousPage)

    #TODO duplicate code in rankUp and -down
    @expose(content_type='text/html; charset=utf-8')
    @validate(validators={"previousPage" : validators.NotEmpty()})
    @error_handler()
    def rankUp(self, id, previousPage, tg_errors=None, **keywords):
        log.debug('rankUp')
        action = session.get(Action,id)
        oldPriority = action.priority
        newPriority = action.priority - 1

        self.rerankContext(action, oldPriority, newPriority)
        action.project.actions.sort( lambda a,b: cmp( (a.priority), (b.priority) ) )
        return dict(project=action.project, context=action.context, tg_template=previousPage, previousPage=previousPage)

    @expose(content_type='text/html; charset=utf-8')
    @validate(validators={"previousPage" : validators.NotEmpty()})
    @error_handler()
    def rankDown(self, id, previousPage, tg_errors=None, **keywords):
        log.debug("randDown-------------")
        action = session.get(Action,id)
        newPriority = action.priority + 1
        oldPriority = action.priority

        self.rerankContext(action, oldPriority, newPriority)
        action.project.actions.sort( lambda a,b: cmp( (a.priority), (b.priority) ) )
        log.debug("Returning------------")
        return dict(project=action.project, context=action.context, tg_template=previousPage, previousPage=previousPage)

    #lower rank of possible action in same context if it has same rank as affected actions new rank
    def rerankContext(self, action, oldPriority, newPriority):
        sameRankContextAction = session.query(Action).select(and_(Action.c.context_id==action.context.id, Action.c.priority==newPriority))
        if(sameRankContextAction):
            sameRankContextAction[0].priority = oldPriority
            #TODO context may have another action with this priority (project can't)
            session.update(sameRankContextAction[0])
        action.priority=newPriority
        session.update(action)
        session.flush()

   ### Action relaction actions
    @expose(content_type='text/html; charset=utf-8')
    @validate(validators={"previousPage" : validators.NotEmpty()})
    @error_handler()
    def delete(self, id, previousPage, **keywords):
        log.debug("delete Action " +id +".")
        action = session.get(Action,id)
        project = action.project
        action.delete()
        action.flush()
        tg.flash("Action deleted")
        return dict(project=project, context=action.context, tg_template=previousPage, previousPage=previousPage)

    @expose(content_type='text/html; charset=utf-8')
    @validate(validators={"previousPage" : validators.NotEmpty()})
    @error_handler()
    def close(self, id, previousPage, **keywords):
        log.debug("close Action " +id +".")
        referer = cherrypy.request.headers.get("REFERER", "/")
        print "cREFERER " +referer
        action = session.get(Action,id)
        project = action.project
        action.closed=1
        action.flush()
        tg.flash("Action updated")
        p = re.compile('context')
        return dict(project=project, context=action.context, tg_template=previousPage,previousPage=previousPage)

    @expose(content_type='text/html; charset=utf-8')
    @validate(validators={"previousPage" : validators.NotEmpty()})
    @error_handler()
    def open(self, id, previousPage, **keywords):
        log.debug("open Action " +id +".")
        action = session.get(Action,id)
        project = action.project
        action.closed=0
        action.flush()
        tg.flash("Action updated")
        return dict(project=project, context=action.context, tg_template=previousPage,previousPage=previousPage)

    @expose(template="kaizen.templates.viewAction", content_type='text/html; charset=utf-8')
    @validate(validators={"previousPage" : validators.NotEmpty()})
    @error_handler()
    def view(self, id, previousPage, **keywords):
        log.debug("view Action " +id +".")
        action = session.get(Action,id)
        return dict(action=action, context=action.context, previousPage=previousPage)